package org.infodavid.common.services;

import java.util.Collection;
import java.util.Locale;

import javax.persistence.PersistenceException;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.joda.time.DateTime;
import org.joda.time.DateTimeZone;

import org.infodavid.common.impl.services.validators.DefaultApplicationSettingsValidator;
import org.infodavid.common.model.IApplicationSettings;
import org.infodavid.common.model.IGenericProperty;
import org.infodavid.common.model.IOrganization;
import org.infodavid.common.model.ModelFactory;
import org.infodavid.common.model.criteria.IApplicationSettingsCriteria;
import org.infodavid.common.model.criteria.IGenericPropertyCriteria;
import org.infodavid.common.reflect.InstantiationHelper;
import org.infodavid.common.services.exceptions.ServiceException;

/**
 * The Class AppllicationSettingsService.
 */
public abstract class ApplicationSettingsService extends
    AbstractEntityService<IApplicationSettings,IApplicationSettings,IApplicationSettingsCriteria> {

	/** The singleton. */
	private static final ApplicationSettingsService SINGLETON;

	/** The Constant log. */
	private static final Log LOGGER = LogFactory.getLog(ApplicationSettingsService.class);

	/** The Constant DEFAULT_LOCALE_PROPERTY. */
	public static final String DEFAULT_LOCALE_PROPERTY = "defaultLocale";

	/** The Constant DEFAULT_TIME_ZONE_PROPERTY. */
	public static final String DEFAULT_TIME_ZONE_PROPERTY = "defaultTimeZone";

	static {
		try {
			SINGLETON = InstantiationHelper.getInstance().newInstance(ApplicationSettingsService.class);
		}
		catch (final Exception e) {
			LOGGER.fatal("Can not instantiate the " + ApplicationSettingsService.class.getName(), e);

			throw new Error(e);
		}
	}

	/**
	 * returns the singleton.
	 * @return <code>CompanyService</code>
	 */
	public static ApplicationSettingsService getInstance() {
		return SINGLETON;
	}

	/**
	 * Instantiates a new service.
	 */
	protected ApplicationSettingsService() {
		super(IApplicationSettings.class, new DefaultApplicationSettingsValidator(), ModelFactory
		    .getInstance().getBuilder(IApplicationSettings.class));
	}

	/**
	 * Find by product.
	 * @param context the context
	 * @param value the value
	 * @return the settings
	 * @throws PersistenceException the persistence exception
	 * @throws ServiceException the service exception
	 */
	public abstract IApplicationSettings findByProduct(IApplicationContext context, String value)
	    throws PersistenceException, ServiceException;

	/**
	 * Find organization.
	 * @param context the context
	 * @return the organization
	 * @throws PersistenceException the persistence exception
	 * @throws ServiceException the service exception
	 */
	public abstract IOrganization findOrganization(IApplicationContext context)
	    throws PersistenceException, ServiceException;

	/**
	 * Gets the default time zone.
	 * @param context the context
	 * @return the default time zone
	 * @throws PersistenceException the persistence exception
	 * @throws ServiceException the service exception
	 */
	public abstract DateTimeZone getDefaultTimeZone(IApplicationContext context)
	    throws PersistenceException, ServiceException;

	/**
	 * Gets the default locale.
	 * @param context the context
	 * @return the default locale
	 * @throws PersistenceException the persistence exception
	 * @throws ServiceException the service exception
	 */
	public abstract Locale getDefaultLocale(IApplicationContext context) throws PersistenceException,
	    ServiceException;

	/**
	 * Find property.
	 * @param context the context
	 * @param property the property
	 * @return the value
	 */
	public abstract String findProperty(IApplicationContext context, String property)
	    throws PersistenceException, ServiceException;

	/**
	 * Find property.
	 * @param context the context
	 * @param property the property
	 * @return the value
	 */
	public abstract Boolean findBooleanProperty(IApplicationContext context, String property)
	    throws PersistenceException, ServiceException;

	/**
	 * Find property.
	 * @param context the context
	 * @param property the property
	 * @return the value
	 */
	public abstract Number findNumberProperty(IApplicationContext context, String property)
	    throws PersistenceException, ServiceException;

	/**
	 * Find the properties using the scope.
	 * @param context the context
	 * @param product the short name of the product
	 * @param criteria the criteria
	 * @param results the resulting properties
	 */
	public abstract void findProperties(IApplicationContext context,
	    Collection<IGenericProperty> results, String product, IGenericPropertyCriteria criteria)
	    throws PersistenceException, ServiceException;

	/**
	 * Sets the properties.
	 * @param context the context
	 * @param product the short name of the product
	 * @param properties the properties to update
	 * @return the modification associated to the application settings entity
	 */
	public abstract DateTime updateProperties(IApplicationContext context, String product,
	    Collection<IGenericProperty> properties) throws PersistenceException, ServiceException;

	/**
	 * Find property.
	 * @param context the context
	 * @param product the product
	 * @param property the property
	 * @return the value
	 */
	public abstract String findProperty(IApplicationContext context, String product, String property)
	    throws PersistenceException, ServiceException;

	/**
	 * Find property.
	 * @param context the context
	 * @param product the product
	 * @param property the property
	 * @return the value
	 */
	public abstract Boolean findBooleanProperty(IApplicationContext context, String product,
	    String property) throws PersistenceException, ServiceException;

	/**
	 * Find property.
	 * @param context the context
	 * @param product the product
	 * @param property the property
	 * @return the value
	 */
	public abstract Number findNumberProperty(IApplicationContext context, String product,
	    String property) throws PersistenceException, ServiceException;
}
